/**
  ******************************************************************************
  * @file   pd_h_adc.c
  * @author Chris
  * @since  2023/11/17
  *
  * @brief  Peripheral driver of ADC(Hardware-Implemented).
  *
  ******************************************************************************
  */
#include "pd_h_gpio.h"
#include "stm32g4xx_ll_adc.h"
#include "stm32g4xx_ll_bus.h"
#include "stm32g4xx_ll_rcc.h"

/** region Declaration and Definition Region */

/** region Variables and Constants Region */
/** endregion Variables and Constants Region */

/** region Function Declaration Region */
/** endregion Function Declaration Region */

/** endregion Declaration and Definition Region */


/** region public function region */
/**
 * @brief   ADC1 初始化
 *
 * @note    无
 * @retval  无
 */
void PD_H_ADC1_Init(void) {
    // 开启 ADC 的时钟
    LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_ADC12);
    // 设置 ADC 时钟源
    LL_RCC_SetADCClockSource(LL_RCC_ADC12_CLKSOURCE_SYSCLK);

    // 配置 ADC 对应的 GPIO：PA0   ------> ADC1_IN1
    PD_H_GPIO_ADC1_Init();

    // ADC 初始化
    LL_ADC_InitTypeDef ADC_InitStruct = {0};
    LL_ADC_StructInit(&ADC_InitStruct);
    ADC_InitStruct.Resolution = LL_ADC_RESOLUTION_12B;      // 数据分辨率：可选 6、8、12 位分辨率
    ADC_InitStruct.DataAlignment = LL_ADC_DATA_ALIGN_RIGHT; // 数据对齐：左、右对齐
    ADC_InitStruct.LowPowerMode = LL_ADC_LP_MODE_NONE;      // 自动延迟转换模式：开、关
    LL_ADC_Init(ADC1, &ADC_InitStruct);

    // ADC 规则组配置
    LL_ADC_REG_InitTypeDef ADC_REG_InitStruct = {0};
    LL_ADC_REG_StructInit(&ADC_REG_InitStruct);
    ADC_REG_InitStruct.TriggerSource = LL_ADC_REG_TRIG_SOFTWARE;          // 规则组外部触发选择：定时器、外部引脚、软件控制位
    ADC_REG_InitStruct.SequencerLength = LL_ADC_REG_SEQ_SCAN_DISABLE;     // 规则组的序列通道数目（ADC_SQR1->L）：0~16
    ADC_REG_InitStruct.SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE; // 规则组的序列是否连续模式（ADC_CFGR->DISCEN）：连续转换、不连续转换
    ADC_REG_InitStruct.ContinuousMode = LL_ADC_REG_CONV_SINGLE;           // 规则组的单次/连续模式（ADC_CFGR->CONT）：连续转换 或 单次转换
    ADC_REG_InitStruct.DMATransfer = LL_ADC_REG_DMA_TRANSFER_NONE;        // 规则组 DMA：使能（ADC_CFGR->DMAEN）；配置（ADC_CFGR->DMACFG）
    ADC_REG_InitStruct.Overrun = LL_ADC_REG_OVR_DATA_PRESERVED;           // 规则组超时模式（ADC_CFGR->OVRMOD）：数据保存或覆盖
    LL_ADC_REG_Init(ADC1, &ADC_REG_InitStruct);

    // ADC 通用寄存器配置
    LL_ADC_CommonInitTypeDef ADC_CommonInitStruct = {0};
    LL_ADC_CommonStructInit(&ADC_CommonInitStruct);
    ADC_CommonInitStruct.CommonClock = LL_ADC_CLOCK_SYNC_PCLK_DIV4;         // ADC 时钟模式：adc_ker_ck、adc_hclk/1,2,4
    ADC_CommonInitStruct.Multimode = LL_ADC_MULTI_INDEPENDENT;              // 双 ADC 模式选择：独立模式；双 ADC 模式；主从 ADC 模式
    ADC_CommonInitStruct.MultiDMATransfer = LL_ADC_MULTI_REG_DMA_EACH_ADC;  // ADC DMA：模式（ADCx_CCR->MDMA）；DMA配置（ADCx_CCR->DMACFG）
    ADC_CommonInitStruct.MultiTwoSamplingDelay = LL_ADC_MULTI_TWOSMP_DELAY_1CYCLE;  // 2 次采样间隔（ADCx_CCR->DELAY）
    LL_ADC_CommonInit(__LL_ADC_COMMON_INSTANCE(ADC1), &ADC_CommonInitStruct);

    LL_ADC_SetGainCompensation(ADC1, 0);            // 增益补偿系数（ADCX_GCOMP）：
    LL_ADC_SetOverSamplingScope(ADC1, LL_ADC_OVS_DISABLE); // 增益补偿模式（ADC_CFGR2->GCOMP）：规则组操作模式；所有通道增益补偿使能。

    // 配置规则组通道
    LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_1, LL_ADC_CHANNEL_1);
    // 配置采样时间
    LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_1, LL_ADC_SAMPLINGTIME_2CYCLES_5);
    // 配置输入通道类型：单端信息 或 差分信号
    LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_1, LL_ADC_SINGLE_ENDED);

    LL_ADC_DisableDeepPowerDown(ADC1);    // ADC_CR->DEEPPWD
    LL_ADC_EnableInternalRegulator(ADC1); // ADC_CR 多个控制位，以及 ADC 电压监管（ ADC_CR->ADVREGEN）

    LL_ADC_Enable(ADC1);                  // ADC_CR 多个控制位，以及 ADC 使能（ADC_CR->ADEN）

    uint32_t wait_loop_index = LL_ADC_DELAY_INTERNAL_REGUL_STAB_US * (SystemCoreClock / (100000 * 2)) / 10;
    while (wait_loop_index--) {
    }
}

/**
 * @brief   获取 ADC1 的值
 *
 * @note    无
 * @retval  无
 */
uint16_t PD_H_ADC1_GetValue(void) {
    // 开始转换
    LL_ADC_REG_StartConversion(ADC1);
    // 等待转换完成
    while (LL_ADC_IsActiveFlag_EOC(ADC1) == RESET) {
    }
    LL_ADC_ClearFlag_EOC(ADC1);

    return LL_ADC_REG_ReadConversionData12(ADC1);
}


/**
 * @brief   ADC1 初始化
 *
 * @note    无
 * @retval  无
 */
void PD_H_ADC2_Init(void) {
    // 开启 ADC 的时钟
    LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_ADC12);
    // 设置 ADC 时钟源
    LL_RCC_SetADCClockSource(LL_RCC_ADC12_CLKSOURCE_SYSCLK);

    // 配置 ADC 对应的 GPIO：PA0   ------> ADC1_IN1
    PD_H_GPIO_ADC2_Init();

    // ADC 初始化
    LL_ADC_InitTypeDef ADC_InitStruct = {0};
    LL_ADC_StructInit(&ADC_InitStruct);
    ADC_InitStruct.Resolution = LL_ADC_RESOLUTION_12B;      // 数据分辨率：可选 6、8、12 位分辨率
    ADC_InitStruct.DataAlignment = LL_ADC_DATA_ALIGN_RIGHT; // 数据对齐：左、右对齐
    ADC_InitStruct.LowPowerMode = LL_ADC_LP_MODE_NONE;      // 自动延迟转换模式：开、关
    LL_ADC_Init(ADC2, &ADC_InitStruct);

    // ADC 规则组配置
    LL_ADC_REG_InitTypeDef ADC_REG_InitStruct = {0};
    LL_ADC_REG_StructInit(&ADC_REG_InitStruct);
    ADC_REG_InitStruct.TriggerSource = LL_ADC_REG_TRIG_SOFTWARE;            // 规则组外部触发选择：定时器、外部引脚、软件控制位
    ADC_REG_InitStruct.SequencerLength = LL_ADC_REG_SEQ_SCAN_DISABLE;       // 规则组的序列通道数目（ADC_SQR1->L）：0~16
    ADC_REG_InitStruct.SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE;   // 规则组的序列是否连续模式（ADC_CFGR->DISCEN）：连续转换、不连续转换
    ADC_REG_InitStruct.ContinuousMode = LL_ADC_REG_CONV_SINGLE;             // 规则组的单次/连续模式（ADC_CFGR->CONT）：连续转换 或 单次转换
    ADC_REG_InitStruct.DMATransfer = LL_ADC_REG_DMA_TRANSFER_NONE;          // 规则组 DMA：使能（ADC_CFGR->DMAEN）；配置（ADC_CFGR->DMACFG）
    ADC_REG_InitStruct.Overrun = LL_ADC_REG_OVR_DATA_PRESERVED;             // 规则组超时模式（ADC_CFGR->OVRMOD）：数据保存或覆盖
    LL_ADC_REG_Init(ADC2, &ADC_REG_InitStruct);

    // ADC 通用寄存器配置
    LL_ADC_CommonInitTypeDef ADC_CommonInitStruct = {0};
    LL_ADC_CommonStructInit(&ADC_CommonInitStruct);
    ADC_CommonInitStruct.CommonClock = LL_ADC_CLOCK_SYNC_PCLK_DIV4;         // ADC 时钟模式：adc_ker_ck、adc_hclk/1,2,4
    ADC_CommonInitStruct.Multimode = LL_ADC_MULTI_INDEPENDENT;              // 双 ADC 模式选择：独立模式；双 ADC 模式；主从 ADC 模式
    LL_ADC_CommonInit(__LL_ADC_COMMON_INSTANCE(ADC2), &ADC_CommonInitStruct);

    LL_ADC_DisableDeepPowerDown(ADC2);    // ADC_CR->DEEPPWD（要开启转换，必须退出 Deep-power mode）
    LL_ADC_EnableInternalRegulator(ADC2); // ADC_CR 多个控制位，以及 ADC 电压监管（ ADC_CR->ADVREGEN）

    LL_ADC_Enable(ADC2);                  // ADC_CR 多个控制位，以及 ADC 使能（ADC_CR->ADEN）

    uint32_t wait_loop_index = LL_ADC_DELAY_INTERNAL_REGUL_STAB_US * (SystemCoreClock / (100000 * 2)) / 10;
    while (wait_loop_index--) {
    }
}

/**
 * @brief   获取 ADC2 的值
 *
 * @note    无
 * @retval  无
 */
uint16_t PD_H_ADC2_GetValue(uint32_t channel) {
    // 开始转换
    LL_ADC_REG_SetSequencerRanks(ADC2, LL_ADC_REG_RANK_1, channel);
    // 配置采样时间
    LL_ADC_SetChannelSamplingTime(ADC2, channel, LL_ADC_SAMPLINGTIME_47CYCLES_5);

    // 开始转换
    LL_ADC_REG_StartConversion(ADC2);
    // 等待转换完成
    while (LL_ADC_IsActiveFlag_EOC(ADC2) == RESET) {
    }
    LL_ADC_ClearFlag_EOC(ADC2);

    return LL_ADC_REG_ReadConversionData12(ADC2);
}
/** endregion public function region */


/** region private function region */

/** endregion private function region */
